<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>神域记牌器</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            padding: 10px;
        }

        .card-row {
            margin-bottom: 5px;
        }

        .card {
            display: inline-block;
            border: 1px solid #ccc;
            padding: 3px;
            margin: 1px;
            width: 20px;
            font-size: 10px;
            text-align: center;
        }

        .row-title {
            display: inline-block;
            margin-right: 10px;
            font-size: 12px;
            font-weight: bold;
            min-width: 60px;
            vertical-align: top;
        }

        .yellow-card {
            background-color: #ff980085;
        }

        .area-container {
            display: flex;
            flex-wrap: wrap;
            align-items: center;
            margin-top: 10px;
        }

        .input-container {
            display: flex;
            align-items: center;
            margin-right: 10px;
        }

        .input-container input,
        .input-container textarea {
            vertical-align: middle;
            margin-right: 5px;
            width: 200px;
            min-width: 150px;
        }

        .input-container textarea {
            height: 100px;
        }

        .card-container {
            display: inline-block;
        }

        .remaining {
            margin: 20px 0;
            font-weight: bold;
            font-size: 13px;
        }

        .library-divider {
            margin: 20px 0;
            text-align: center;
            font-weight: bold;
            display: flex;
            align-items: center;
            font-size: 14px;
        }

        .library-divider::before,
        .library-divider::after {
            content: "";
            flex: 1;
            border-top: 1px solid #ccc;
            margin: 0 10px;
        }

        @media (max-width: 600px) {
            .area-container {
                flex-direction: column;
                align-items: flex-start;
            }

            .input-container {
                margin-bottom: 10px;
            }
        }
    </style>
</head>

<body>
<!-- 万牌行 -->
<div class="card-row">
    <span class="row-title">万牌</span>
</div>
<!-- 筒牌行 -->
<div class="card-row">
    <span class="row-title">筒牌</span>
</div>
<!-- 索牌行 -->
<div class="card-row">
    <span class="row-title">索牌</span>
</div>
<!-- 字牌行 -->
<div class="card-row">
    <span class="row-title">字牌</span>
</div>
<div id="remaining-change-cards" class="remaining">剩余换牌数 49</div>
<!-- 牌库分界线 -->
<div class="library-divider">牌库分界线</div>
<!-- 公开牌行 -->
<div class="area-container">
    <span class="row-title">公开牌</span>
    <div class="input-container">
        <textarea id="public-input" placeholder="可多行输入，每行例:19m34p58s2567z"></textarea>
        <button onclick="resetAndParse()">设置</button>
    </div>
    <div class="card-container" id="public-cards"></div>
</div>

<!-- 宝牌失效区域 -->
<div class="area-container">
    <span class="row-title">宝牌失效</span>
    <div class="input-container">
        <input type="text" id="dora-invalid-input" placeholder="例:m p s">
        <button onclick="resetAndParse()">设置</button>
    </div>
</div>

<!-- 宝牌区 -->
<div class="area-container">
    <span class="row-title">宝牌指示牌</span>
    <div class="input-container">
        <input type="text" id="dora-input" placeholder="例:19m34p58s2567z">
        <button onclick="resetAndParse()">设置</button>
    </div>
    <div class="card-container" id="dora-cards"></div>
</div>

<!-- 手牌区 -->
<div class="area-container">
    <span class="row-title">手牌</span>
    <div class="input-container">
        <input type="text" id="hand-input" placeholder="例:19m34p58s2567z">
        <button onclick="resetAndParse()">设置</button>
    </div>
    <div class="card-container" id="hand-cards"></div>
</div>

<!-- 换掉区 -->
<div class="area-container">
    <span class="row-title">换掉的牌</span>
    <div class="input-container">
        <textarea id="change-input" placeholder="可多行输入，每行例:19m34p58s2567z"></textarea>
        <button onclick="resetAndParse()">设置</button>
    </div>
    <div class="card-container" id="change-cards"></div>
</div>

<!-- 打掉区 -->
<div class="area-container">
    <span class="row-title">打/锁的牌</span>
    <div class="input-container">
        <textarea id="discard-input" placeholder="可多行输入，每行例:19m34p58s2567z"></textarea>
        <button onclick="resetAndParse()">设置</button>
    </div>
    <div class="card-container" id="discard-cards"></div>
</div>

<script>
    // 定义麻将牌的基本数组
    const numbers = [1, 9];
    const suits = ['万', '筒', '索'];
    const ziCards = ['东', '南', '西', '北', '白', '发', '中'];
    const windCards = ['东', '南', '西', '北'];
    const dragonCards = ['白', '发', '中'];
    // 初始化剩余换牌数
    let remainingChangeCards = 49;

    // 获取所有的行容器
    const cardRows = document.querySelectorAll('.card-row');

    // 生成并添加万子牌
    function generateWanCards() {
        const wanCards = [];
        numbers.forEach(num => {
            const card = `${num}万`;
            Array.from({ length: 4 }).forEach(() => wanCards.push(card));
        });
        const wanRow = cardRows[0];
        // 清空牌元素，保留标题
        while (wanRow.children.length > 1) {
            wanRow.removeChild(wanRow.lastChild);
        }
        wanCards.forEach(card => {
            const cardElement = document.createElement('div');
            cardElement.classList.add('card');
            cardElement.textContent = card;
            wanRow.appendChild(cardElement);
        });
    }

    // 生成并添加筒子牌
    function generateTongCards() {
        const tongCards = [];
        const allNumbers = Array.from({ length: 9 }, (_, i) => i + 1);
        allNumbers.forEach(num => {
            const card = `${num}筒`;
            Array.from({ length: 4 }).forEach(() => tongCards.push(card));
        });
        const tongRow = cardRows[1];
        // 清空牌元素，保留标题
        while (tongRow.children.length > 1) {
            tongRow.removeChild(tongRow.lastChild);
        }
        tongCards.forEach(card => {
            const cardElement = document.createElement('div');
            cardElement.classList.add('card');
            cardElement.textContent = card;
            tongRow.appendChild(cardElement);
        });
    }

    // 生成并添加索子牌
    function generateSuoCards() {
        const suoCards = [];
        const allNumbers = Array.from({ length: 9 }, (_, i) => i + 1);
        allNumbers.forEach(num => {
            const card = `${num}索`;
            Array.from({ length: 4 }).forEach(() => suoCards.push(card));
        });
        const suoRow = cardRows[2];
        // 清空牌元素，保留标题
        while (suoRow.children.length > 1) {
            suoRow.removeChild(suoRow.lastChild);
        }
        suoCards.forEach(card => {
            const cardElement = document.createElement('div');
            cardElement.classList.add('card');
            cardElement.textContent = card;
            suoRow.appendChild(cardElement);
        });
    }

    // 生成并添加字牌
    function generateZiCards() {
        const ziFullCards = [];
        ziCards.forEach(zi => {
            const card = zi;
            Array.from({ length: 4 }).forEach(() => ziFullCards.push(card));
        });
        const ziRow = cardRows[3];
        // 清空牌元素，保留标题
        while (ziRow.children.length > 1) {
            ziRow.removeChild(ziRow.lastChild);
        }
        ziFullCards.forEach(card => {
            const cardElement = document.createElement('div');
            cardElement.classList.add('card');
            cardElement.textContent = card;
            ziRow.appendChild(cardElement);
        });
    }

    // 页面加载完成后生成完整牌库
    window.addEventListener('load', () => {
        generateWanCards();
        generateTongCards();
        generateSuoCards();
        generateZiCards();
    });

    // 重置牌库
    function resetCardLibrary() {
        generateWanCards();
        generateTongCards();
        generateSuoCards();
        generateZiCards();
        remainingChangeCards = 49;
        document.getElementById('remaining-change-cards').textContent = `剩余换牌数 ${remainingChangeCards}`;
    }

    // 计算宝牌和指示牌
    function calculateDoraAndIndicators(input) {
        const regex = /(\d+)([mpsz])/g;
        let match;
        const doraList = [];
        const indicatorList = [];

        while ((match = regex.exec(input))!== null) {
            const numbers = match[1].split('');
            const suit = match[2];
            numbers.forEach(num => {
                let cardName;
                if (suit === 'm') {
                    cardName = `${num}万`;
                } else if (suit === 'p') {
                    cardName = `${num}筒`;
                } else if (suit === 's') {
                    cardName = `${num}索`;
                } else if (suit === 'z') {
                    const ziIndex = parseInt(num) - 1;
                    cardName = ziCards[ziIndex];
                }

                // 计算宝牌
                let doraCardName;
                if (suit === 'm') {
                    if (num === '1') {
                        doraCardName = '9万';
                    } else if (num === '9') {
                        doraCardName = '1万';
                    } else {
                        doraCardName = `${parseInt(num) + 1}万`;
                    }
                } else if (suit === 'p' || suit === 's') {
                    let nextNum = parseInt(num) + 1;
                    if (nextNum > 9) {
                        nextNum = 1;
                    }
                    doraCardName = `${nextNum}${suit === 'p' ? '筒' : '索'}`;
                } else if (suit === 'z') {
                    const ziIndex = parseInt(num) - 1;
                    const currentCard = ziCards[ziIndex];
                    if (windCards.includes(currentCard)) {
                        const windIndex = windCards.indexOf(currentCard);
                        const nextWindIndex = (windIndex + 1) % 4;
                        doraCardName = windCards[nextWindIndex];
                    } else {
                        const dragonIndex = dragonCards.indexOf(currentCard);
                        const nextDragonIndex = (dragonIndex + 1) % 3;
                        doraCardName = dragonCards[nextDragonIndex];
                    }
                }
                doraList.push(doraCardName);
                indicatorList.push(cardName);
            });
        }
        return { doraList, indicatorList };
    }

    // 移除指定牌
    function removeCardsFromLibrary(cardList) {
        const allCardElements = document.querySelectorAll('.card');
        const cardCount = {};
        cardList.forEach(card => {
            cardCount[card] = (cardCount[card] || 0) + 1;
        });

        allCardElements.forEach(cardElement => {
            const cardName = cardElement.textContent;
            if (cardCount[cardName] > 0) {
                cardElement.remove();
                cardCount[cardName]--;
            }
        });
    }

    // 标记宝牌和指示牌为黄色
    function markYellowCards(doraList, indicatorList, doraInvalidInput) {
        const allCardElements = document.querySelectorAll('.card');
        allCardElements.forEach(cardElement => {
            const cardName = cardElement.textContent;
            if (shouldMarkYellow(cardName, doraList, indicatorList, doraInvalidInput)) {
                cardElement.classList.add('yellow-card');
            }
        });
    }

    // 判断是否应该标记为黄色
    function shouldMarkYellow(cardName, doraList, indicatorList, doraInvalidInput) {
        if (doraInvalidInput.includes('m') && cardName.includes('万')) {
            return false;
        }
        if (doraInvalidInput.includes('p') && cardName.includes('筒')) {
            return false;
        }
        if (doraInvalidInput.includes('s') && cardName.includes('索')) {
            return false;
        }
        return doraList.includes(cardName) || indicatorList.includes(cardName);
    }

    // 解析区域输入字符串
    function parseAreaInput(input, containerId) {
        const lines = input.split('\n');
        const cardList = [];
        const container = document.getElementById(containerId);
        container.innerHTML = '';

        lines.forEach(line => {
            const regex = /(\d+)([mpsz])/g;
            let match;

            while ((match = regex.exec(line))!== null) {
                const numbers = match[1].split('');
                const suit = match[2];
                numbers.forEach(num => {
                    let cardName;
                    if (suit === 'm') {
                        cardName = `${num}万`;
                    } else if (suit === 'p') {
                        cardName = `${num}筒`;
                    } else if (suit === 's') {
                        cardName = `${num}索`;
                    } else if (suit === 'z') {
                        const ziIndex = parseInt(num) - 1;
                        cardName = ziCards[ziIndex];
                    }

                    const cardElement = document.createElement('div');
                    cardElement.classList.add('card');
                    cardElement.textContent = cardName;
                    container.appendChild(cardElement);

                    cardList.push(cardName);
                });
            }
        });
        return cardList;
    }

    // 重置并解析宝牌和各区域牌
    function resetAndParse() {
        // 重置牌库
        resetCardLibrary();

        const doraInput = document.getElementById('dora-input').value;
        const handInput = document.getElementById('hand-input').value;
        const changeInput = document.getElementById('change-input').value;
        const discardInput = document.getElementById('discard-input').value;
        const publicInput = document.getElementById('public-input').value;
        // 获取宝牌失效输入框的值
        const doraInvalidInput = document.getElementById('dora-invalid-input').value.trim();

        const allCardElements = document.querySelectorAll('.card');
        // 移除所有宝牌的黄色背景样式
        allCardElements.forEach(cardElement => {
            cardElement.classList.remove('yellow-card');
        });

        // 计算宝牌和指示牌
        const { doraList, indicatorList } = calculateDoraAndIndicators(doraInput);

        // 显示宝牌指示牌
        const doraCardsContainer = document.getElementById('dora-cards');
        doraCardsContainer.innerHTML = '';
        indicatorList.forEach(indicator => {
            const cardElement = document.createElement('div');
            cardElement.classList.add('card');
            cardElement.textContent = indicator;
            doraCardsContainer.appendChild(cardElement);
        });

        // 移除牌库区的宝牌指示牌
        removeCardsFromLibrary(indicatorList);

        // 解析手牌区
        const handList = parseAreaInput(handInput, 'hand-cards');
        removeCardsFromLibrary(handList);

        // 解析换掉区
        const changeList = parseAreaInput(changeInput, 'change-cards');
        removeCardsFromLibrary(changeList);
        // 更新剩余换牌数
        remainingChangeCards -= changeList.length;
        document.getElementById('remaining-change-cards').textContent = `剩余换牌数 ${remainingChangeCards}`;

        // 解析打掉区
        const discardList = parseAreaInput(discardInput, 'discard-cards');
        removeCardsFromLibrary(discardList);

        // 解析公开牌区
        const publicList = parseAreaInput(publicInput, 'public-cards');
        removeCardsFromLibrary(publicList);

        // 将宝牌、宝牌指示牌和各区域手牌中的宝牌、宝牌指示牌变黄色，排除失效类型
        markYellowCards(doraList, indicatorList, doraInvalidInput);
        const allAreaCardElements = document.querySelectorAll('#hand-cards .card, #change-cards .card, #discard-cards .card, #public-cards .card');
        allAreaCardElements.forEach(cardElement => {
            const cardName = cardElement.textContent;
            if (shouldMarkYellow(cardName, doraList, indicatorList, doraInvalidInput)) {
                cardElement.classList.add('yellow-card');
            }
        });
    }
</script>
</body>

</html>
